package buffer

import (
	"errors"
	"sync"
	"sync/atomic"
	"worm/base"
	"worm/pool"
)

type myBuffer struct {
	pool.Buffer
	//存放数据的管道
	ch chan interface{}
	//缓冲器的关闭状态 0为未关闭，1为关闭
	closed uint32
	//读写锁
	closingLock sync.RWMutex
}

func NewBuffer(size uint32) (pool.Buffer, error) {
	if size == 0 {
		return nil, errors.New(string(base.BUFFER_SIZE_ERROR))
	}
	return &myBuffer{
		ch: make(chan interface{}, size),
	}, nil
}

func (buf *myBuffer) Len() uint32 {
	l := len(buf.ch)
	return uint32(l)
}

func (buf *myBuffer) Cap() uint32 {
	c := cap(buf.ch)
	return uint32(c)
}

func (buf *myBuffer) Close() bool {
	if atomic.CompareAndSwapUint32(&buf.closed, 0, 1) {
		buf.closingLock.Lock()
		close(buf.ch)
		buf.closingLock.Unlock()
		return true
	}
	return false
}

func (buf *myBuffer) Closed() bool {
	if atomic.LoadUint32(&buf.closed) == 0 {
		return true
	}
	return false
}

func (buf *myBuffer) Put(duaum interface{}) (ok bool, err error) {
	//锁
	buf.closingLock.Lock()
	//解锁
	defer buf.closingLock.Unlock()
	//关闭状态下，退出
	if buf.Closed() {
		return false, errors.New(string(base.BUFFER_CLOSED))
	}
	select {
	case buf.ch <- duaum:
		ok = true
	default:
		ok = false
	}
	return
}

func (buf *myBuffer) Get() (interface{}, error) {
	select {
	case duaum, ok := <-buf.ch:
		if !ok {
			return nil, errors.New(string(base.BUFFER_GET_CH))
		}
		return duaum, nil
	default:
		return nil, nil
	}
}
